package com.wy.blocking_queue_impl;

/**
 * @author 美女
 * @date 2022/05/02 15:28
 **/
//实现了一个初级的一对一的阻塞队列
public class MyArrayBlockingQueue {
    private long[] array;
    //队首下标
    private int frontIndex;//永远在队列的第一个元素位置
    //队尾下标
    private int rearIndex;//永远在队列的最后一个元素的下一个位置
    private int size;//大小

    public MyArrayBlockingQueue(int capacity){
        array=new long[capacity];
        frontIndex=0;
        rearIndex=0;
        size=0;
    }

    //阻塞的放入
    public synchronized void put(long e) throws InterruptedException {
        //判断队列是否已满
        //考虑到假唤醒的情况，所以判断条件建议用while
        //醒过来之后再确定条件是否满足，如果不满足，才走到预期处
        while(array.length==size){
            //已满-等待
            this.wait();//同步方法就是对this加的锁，所以直接this.wait()即可。省区再加锁一次的过程
        }
        //预期：走到此处，队列一定不是满的
        array[rearIndex]=e;
        rearIndex++;
        if(rearIndex==array.length){
            rearIndex=0;//循环回来
        }
        size++;
        notify();
    }

    //阻塞的拿取
    public synchronized long take() throws InterruptedException {
        while (size==0){
            //空
            wait();//就是this.wait();
        }
        long e=array[frontIndex];//从队首取元素
        frontIndex++;
        if(frontIndex==array.length){
            frontIndex=0;
        }
        size--;
        notify();//唤醒放入操作的线程
        return e;
    }
}
//生产者会调用put操作，唤醒调用take的消费者
//调用take的消费者，会唤醒调用put的生产者
//这两者是一个互相唤醒的过程